package ru.galiauir.gui;

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;

import ru.galiauir.engine.Simulator;

public class MainForm {
	private static final int TOP_MARGIN = 10;
	private static final int LEFT_MARGIN = 10;
	private static final int FIELD_HEIGHT = 30;
	private static final int LABEL_WIDTH = 200;
	private static final int FIELD_WIDTH = 100;
	private static final int FIELD_STEP = FIELD_HEIGHT + 10;
	private static final int FIELD_MARGIN_LEFT = 5;

	private static final int FRAMEWIDTH = LEFT_MARGIN + LABEL_WIDTH + FIELD_WIDTH + LEFT_MARGIN;
	private static final int FRAMEHEIGHT = TOP_MARGIN + 10 * FIELD_STEP;

	private JFrame 		jfrmProtocols;
	private JButton 	jcmdSet;
	private Container 	cp;

	private int validityFlags = 127;

	private JLabel jlblAlpha;
	private JTextField jtxtAlpha;

	private JLabel jlblDays;
	private JTextField jtxtDays;

	private JLabel jlblInitUsers;
	private JTextField jtxtInitUsers;

	private JLabel jlblBeta;
	private JTextField jtxtBeta;

	private JLabel jlblAveragePurchaseAmount;
	private JTextField jtxtAveragePurchaseAmount;

	private JLabel jlblPurchaseAmountDispersia;
	private JTextField jtxtPurchaseAmountDispersia;

	private JLabel jlblYRatio;
	private JTextField jtxtYRatio;

	private JLabel jlblLog;
	private JCheckBox jchkLog;

	private class ButtonPressListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			if (Integer.parseInt(jtxtPurchaseAmountDispersia.getText()) > Integer.parseInt(jtxtAveragePurchaseAmount.getText())) {
				jtxtPurchaseAmountDispersia.setBackground(Color.RED);
				((IntKeyPress) jtxtPurchaseAmountDispersia.getKeyListeners()[0]).setMaxValue(Integer.parseInt(jtxtAveragePurchaseAmount.getText()));
				validityFlags &= (~32);
				changeButtonState();
				cp.repaint();
			} else {
				jfrmProtocols.dispose();
				Simulator.simulate(Float.parseFloat(jtxtAlpha.getText()),
									Integer.parseInt(jtxtDays.getText()),
									Integer.parseInt(jtxtInitUsers.getText()),
									Float.parseFloat(jtxtBeta.getText()),
									Long.parseLong(jtxtAveragePurchaseAmount.getText()),
									Long.parseLong(jtxtPurchaseAmountDispersia.getText()),
									Integer.parseInt(jtxtYRatio.getText()),
									0.75f,//TODO: make parametrized
									false,
									jchkLog.isSelected(),
									false,
									null,
									null);
			}
		}
	}

	private void changeButtonState() {
		if (validityFlags != 127) {
			jcmdSet.setEnabled(false);
		} else {
			jcmdSet.setEnabled(true);
		}
	}

	private class IntKeyPress implements KeyListener {
		private int maxValue = Integer.MAX_VALUE;
		private int minValue = Integer.MIN_VALUE;
		private JTextField field;
		private int validityFlag;

		public IntKeyPress(int minValue, int maxValue, JTextField field, int validityFlag) {
			this.maxValue = maxValue;
			this.minValue = minValue;
			this.field = field;
			this.validityFlag = validityFlag;
		}

		public void setMaxValue(int maxValue) {
			this.maxValue = maxValue;
		}

		public void keyPressed(KeyEvent e) {}
		public void keyReleased(KeyEvent e) {
			checkValue();
		}
		public void keyTyped(KeyEvent e) {
			char c = e.getKeyChar();
			if ( !( (c >= KeyEvent.VK_0) && (c <= KeyEvent.VK_9) || (c == KeyEvent.VK_DELETE) || (c == KeyEvent.VK_BACK_SPACE) ) ) {
				e.consume();
			}
		}

		private void checkValue() {
			try {
				int value = Integer.parseInt(field.getText());
				if (value < minValue || value > maxValue) {
					field.setBackground(Color.RED);
					validityFlags &= (~validityFlag);
				} else {
					field.setBackground(Color.WHITE);
					validityFlags |= validityFlag;
				}
			} catch (NumberFormatException nfe) {
				field.setBackground(Color.RED);
				validityFlags &= (~validityFlag);
			}
			changeButtonState();
			cp.repaint();
		}
	}

	private class FloatKeyPress implements KeyListener {
		private float maxValue = 1f;
		private float minValue = 0f;
		private JTextField field;
		private int validityFlag;

		public FloatKeyPress(float minValue, float maxValue, JTextField field, int validityFlag) {
			this.maxValue = maxValue;
			this.minValue = minValue;
			this.field = field;
			this.validityFlag = validityFlag;
		}

		public void keyPressed(KeyEvent e) {}
		public void keyReleased(KeyEvent e) {
			checkValue();
		}
		public void keyTyped(KeyEvent e) {
			char c = e.getKeyChar();
			if ( !( (c >= KeyEvent.VK_0) && (c <= KeyEvent.VK_9) || (c == KeyEvent.VK_DELETE) || (c == KeyEvent.VK_BACK_SPACE) || (c == '.')) ) {
				e.consume();
			}
		}

		private void checkValue() {
			try {
				float value = Float.parseFloat(field.getText());
				if (value < minValue || value > maxValue) {
					field.setBackground(Color.RED);
					validityFlags &= (~validityFlag);
				} else {
					field.setBackground(Color.WHITE);
					validityFlags |= validityFlag;
				}
			} catch (NumberFormatException nfe) {
				field.setBackground(Color.RED);
				validityFlags &= (~validityFlag);
			}
			changeButtonState();
			cp.repaint();
		}
	}


	public MainForm() {
		jfrmProtocols = new JFrame("Настройки модели");
		jfrmProtocols.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		jfrmProtocols.setSize(FRAMEWIDTH,FRAMEHEIGHT);
		jfrmProtocols.setResizable(false);
		setFrameLocation(jfrmProtocols);
		jfrmProtocols.addWindowListener(new WindowAdapter(){});

		createObjects();
		initObjects();
		addObjects();

//		String showWindow = (String) GlobalSettings.getProperty("show.init.param.window", "1");
//		if ( showWindow.equals("1") ) {
			jfrmProtocols.setVisible(true);
//		} else {
//			jfrmProtocols.setVisible(false);
//			jcmdSet.doClick();
//		}
	}

	private void setFrameLocation(JFrame frm) {
		Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
		int left = ((int) (dim.getWidth() - frm.getWidth()) / 2);
		int top = ((int) (dim.getHeight() - frm.getHeight()) / 3);
		frm.setLocation(left, top);
	}

	private void createObjects(){
//		jcbxProtocolList 	= new JComboBox(usedProtocols);
		jlblAlpha = new JLabel(String.valueOf('\u03B1'), JLabel.RIGHT);
		jtxtAlpha = new JTextField(String.valueOf(0.001f));

		jlblDays = new JLabel("Duration, days", JLabel.RIGHT);
		jtxtDays = new JTextField(String.valueOf(720));

		jlblInitUsers = new JLabel("Initial users", JLabel.RIGHT);
		jtxtInitUsers = new JTextField(String.valueOf(1000));

		jlblBeta = new JLabel(String.valueOf('\u03B2'), JLabel.RIGHT);
		jtxtBeta = new JTextField(String.valueOf(0.03f));

		jlblAveragePurchaseAmount = new JLabel("Average purchase amount", JLabel.RIGHT);
		jtxtAveragePurchaseAmount = new JTextField(String.valueOf(800));

		jlblPurchaseAmountDispersia = new JLabel("Purchase amount dispersia", JLabel.RIGHT);
		jtxtPurchaseAmountDispersia = new JTextField(String.valueOf(400));

		jlblYRatio = new JLabel("Parent bonus ratio", JLabel.RIGHT);
		jtxtYRatio = new JTextField(String.valueOf(4));

		jlblLog = new JLabel("Log only last day structure", JLabel.RIGHT);
		jchkLog = new JCheckBox();

//		jtxtLuno			= new JTextField(String.valueOf('\u03B1'));
//		jlblLuno			= new JLabel("LUNO   = ", JLabel.CENTER);
//		jtxtScreenTemplate 	= new JTextField("sdgds");
//		jlblScreen			= new JLabel("Путь и шаблон для экранов:", JLabel.LEFT);
		jcmdSet 			= new JButton("OK");
	}

	private void initObjects(){
//		jcbxProtocolList.setBorder(new BevelBorder(BevelBorder.LOWERED));
//		jcbxProtocolList.setBounds(50, 30, 200, 50);
//		jcbxProtocolList.addActionListener(new ProtocolList_Select());
//		jcbxProtocolList.setMaximumRowCount(4);
//		jcbxProtocolList.setSelectedIndex(getDefaultProtocol());
//		jcbxProtocolList.setToolTipText("Выберите один из перечисленных в списке протоколов");
//		jcbxProtocolList.setVisible(true);

		jlblAlpha.setBounds(LEFT_MARGIN, TOP_MARGIN, LABEL_WIDTH, FIELD_HEIGHT);
		jlblAlpha.setToolTipText("Укажите вероятность приглашения человека");
		jlblAlpha.setVisible(true);

		jtxtAlpha.setBounds(LEFT_MARGIN + LABEL_WIDTH + FIELD_MARGIN_LEFT, TOP_MARGIN, FIELD_WIDTH, FIELD_HEIGHT);
		jtxtAlpha.addKeyListener(new FloatKeyPress(0.0001f, 0.1f, jtxtAlpha, 1));
		jtxtAlpha.setToolTipText("Введите вероятность приглашения человека [0.0001;0.01]");
		jtxtAlpha.setVisible(true);

		jlblDays.setBounds(LEFT_MARGIN, TOP_MARGIN + 1 * FIELD_STEP, LABEL_WIDTH, FIELD_HEIGHT);
		jlblDays.setToolTipText("Укажите количество дней моделирования");
		jlblDays.setVisible(true);

		jtxtDays.setBounds(LEFT_MARGIN + LABEL_WIDTH + FIELD_MARGIN_LEFT, TOP_MARGIN + 1 * FIELD_STEP, FIELD_WIDTH, FIELD_HEIGHT);
		jtxtDays.addKeyListener(new IntKeyPress(0, 3650, jtxtDays, 2));
		jtxtDays.setToolTipText("Введите количество дней моделирования [0;3650]");
		jtxtDays.setVisible(true);

		jlblInitUsers.setBounds(LEFT_MARGIN, TOP_MARGIN + 2 * FIELD_STEP, LABEL_WIDTH, FIELD_HEIGHT);
		jlblInitUsers.setToolTipText("Укажите начальное количество пользователей");
		jlblInitUsers.setVisible(true);

		jtxtInitUsers.setBounds(LEFT_MARGIN + LABEL_WIDTH + FIELD_MARGIN_LEFT, TOP_MARGIN + 2 * FIELD_STEP, FIELD_WIDTH, FIELD_HEIGHT);
		jtxtInitUsers.addKeyListener(new IntKeyPress(0, 1000, jtxtInitUsers, 4));
		jtxtInitUsers.setToolTipText("Введите начальное количество пользователей [0;1000]");
		jtxtInitUsers.setVisible(true);

		jlblBeta.setBounds(LEFT_MARGIN, TOP_MARGIN + 3 * FIELD_STEP, LABEL_WIDTH, FIELD_HEIGHT);
		jlblBeta.setToolTipText("Укажите вероятность совершения покупки");
		jlblBeta.setVisible(true);

		jtxtBeta.setBounds(LEFT_MARGIN + LABEL_WIDTH + FIELD_MARGIN_LEFT, TOP_MARGIN + 3 * FIELD_STEP, FIELD_WIDTH, FIELD_HEIGHT);
		jtxtBeta.addKeyListener(new FloatKeyPress(0f, 1f, jtxtBeta, 8));
		jtxtBeta.setToolTipText("Введите вероятность совершения покупки [0.0;1.0]");
		jtxtBeta.setVisible(true);

		jlblAveragePurchaseAmount.setBounds(LEFT_MARGIN, TOP_MARGIN + 4 * FIELD_STEP, LABEL_WIDTH, FIELD_HEIGHT);
		jlblAveragePurchaseAmount.setToolTipText("Укажите среднюю сумму покупки");
		jlblAveragePurchaseAmount.setVisible(true);

		jtxtAveragePurchaseAmount.setBounds(LEFT_MARGIN + LABEL_WIDTH + FIELD_MARGIN_LEFT, TOP_MARGIN + 4 * FIELD_STEP, FIELD_WIDTH, FIELD_HEIGHT);
		jtxtAveragePurchaseAmount.addKeyListener(new IntKeyPress(0, 100000, jtxtAveragePurchaseAmount, 16));
		jtxtAveragePurchaseAmount.setToolTipText("Введите среднюю сумму покупки [0;100000]");
		jtxtAveragePurchaseAmount.setVisible(true);

		jlblPurchaseAmountDispersia.setBounds(LEFT_MARGIN, TOP_MARGIN + 5 * FIELD_STEP, LABEL_WIDTH, FIELD_HEIGHT);
		jlblPurchaseAmountDispersia.setToolTipText("Укажите дисперсию суммы покупки");
		jlblPurchaseAmountDispersia.setVisible(true);

		jtxtPurchaseAmountDispersia.setBounds(LEFT_MARGIN + LABEL_WIDTH + FIELD_MARGIN_LEFT, TOP_MARGIN + 5 * FIELD_STEP, FIELD_WIDTH, FIELD_HEIGHT);
		jtxtPurchaseAmountDispersia.addKeyListener(new IntKeyPress(0, 100000, jtxtPurchaseAmountDispersia, 32));
		jtxtPurchaseAmountDispersia.setToolTipText("Введите дисперсию суммы покупки [0;100000]");
		jtxtPurchaseAmountDispersia.setVisible(true);

		jlblYRatio.setBounds(LEFT_MARGIN, TOP_MARGIN + 6 * FIELD_STEP, LABEL_WIDTH, FIELD_HEIGHT);
		jlblYRatio.setToolTipText("Укажите коэффициент расчета бонуса предшественников");
		jlblYRatio.setVisible(true);

		jtxtYRatio.setBounds(LEFT_MARGIN + LABEL_WIDTH + FIELD_MARGIN_LEFT, TOP_MARGIN + 6 * FIELD_STEP, FIELD_WIDTH, FIELD_HEIGHT);
		jtxtYRatio.addKeyListener(new IntKeyPress(0, 100, jtxtYRatio, 64));
		jtxtYRatio.setToolTipText("Введите коэффициент расчета бонуса предшественников (сумма бонусов за 100 рублей покупки) [0;100]");
		jtxtYRatio.setVisible(true);

		jlblLog.setBounds(LEFT_MARGIN, TOP_MARGIN + 7 * FIELD_STEP, LABEL_WIDTH, FIELD_HEIGHT);
		jlblLog.setToolTipText("Логировать только последний день?");
		jlblLog.setVisible(true);

		jchkLog.setBounds(LEFT_MARGIN + LABEL_WIDTH + FIELD_MARGIN_LEFT, TOP_MARGIN + 7 * FIELD_STEP, FIELD_WIDTH, FIELD_HEIGHT);
		jchkLog.setSelected(true);
		jchkLog.setVisible(true);

		jcmdSet.setBounds(LEFT_MARGIN, TOP_MARGIN + 8 * FIELD_STEP, 100, 20);
		jcmdSet.addActionListener(new ButtonPressListener());
		jcmdSet.setToolTipText("Нажмите для запуска модели");
		jcmdSet.setVisible(true);
	}

	private void addObjects() {
		cp = jfrmProtocols.getContentPane();
		cp.setLayout(null);
		cp.add(jtxtAlpha);
		cp.add(jlblAlpha);

		cp.add(jtxtDays);
		cp.add(jlblDays);

		cp.add(jtxtInitUsers);
		cp.add(jlblInitUsers);

		cp.add(jtxtBeta);
		cp.add(jlblBeta);

		cp.add(jtxtAveragePurchaseAmount);
		cp.add(jlblAveragePurchaseAmount);

		cp.add(jtxtPurchaseAmountDispersia);
		cp.add(jlblPurchaseAmountDispersia);

		cp.add(jtxtYRatio);
		cp.add(jlblYRatio);

		cp.add(jchkLog);
		cp.add(jlblLog);

		cp.add(jcmdSet);
	}
}
